springboot注解@SpringBootApplication源码解析 您所在的位置:网站首页 springboot 源码解析 springboot注解@SpringBootApplication源码解析

springboot注解@SpringBootApplication源码解析

2023-03-29 08:26| 来源: 网络整理| 查看: 265

springboot启动通过main方法,在main方法所在的类添加了SpringBootApplication注解

示例代码

启动类Application.class

package com.netepg; @SpringBootApplication public class App{ public static void main(String[] args) { SpringApplication.run(App.class, args); } } SpringBootApplication注解元数据

首先查看下在springboot中SpringBootApplication注解都有哪些信息

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication { /** * Exclude specific auto-configuration classes such that they will never be applied. * @return the classes to exclude */ @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "exclude") Class[] exclude() default {}; /** * Exclude specific auto-configuration class names such that they will never be * applied. * @return the class names to exclude * @since 1.3.0 */ @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "excludeName") String[] excludeName() default {}; /** * Base packages to scan for annotated components. Use {@link #scanBasePackageClasses} * for a type-safe alternative to String-based package names. * @return base packages to scan * @since 1.3.0 */ @AliasFor(annotation = ComponentScan.class, attribute = "basePackages") String[] scanBasePackages() default {}; /** * Type-safe alternative to {@link #scanBasePackages} for specifying the packages to * scan for annotated components. The package of each class specified will be scanned. *

* Consider creating a special no-op marker class or interface in each package that * serves no purpose other than being referenced by this attribute. * @return base packages to scan * @since 1.3.0 */ @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses") Class[] scanBasePackageClasses() default {}; }

注解主要包括SpringBootConfiguration、EnableAutoConfiguration、ComponentScan 1、SpringBootConfiguration注解表明当前类是配置类

image.png

2、EnableAutoConfiguration注解表示开启自动配置 3、ComponentScan表示,扫描过滤

EnableAutoConfiguration注解 @AutoConfigurationPackage @Import(EnableAutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { }

这个注解元数据包括AutoConfigurationPackage和使用import导入了EnableAutoConfigurationImportSelector类 1、AutoConfigurationPackage注解导入AutoConfigurationPackages.Registrar类

image.png

AutoConfigurationPackages.Registrar类实现了ImportBeanDefinitionRegistrar

image.png AutoConfigurationPackages#register BEAN = "org.springframework.boot.autoconfigure.AutoConfigurationPackages" 把AutoConfigurationPackages注册到bean工厂,并把当前包名设置为ConstructorArgumentValues参数 image.png

实现了ImportBeanDefinitionRegistrar的类,也会在生成bean的生命周期的import过程中,调用registerBeanDefinitions方法

2、EnableAutoConfigurationImportSelector

在spring容器实例化Bean的过程中,在解析配置类时,会对实现了DeferredImportSelector的导入类调用selectImports方法

2.1、selectImports

AutoConfigurationImportSelector#selectImports 加载元数据

image.png

AutoConfigurationMetadataLoader#loadMetadata(java.lang.ClassLoader)

image.png 将会加载spring-autoconfigure-metadata.properties文件的数据。加载过程把配置文件中的值加载到Properties然后封装成AutoConfigurationMetadata对象返回 image.png 对于封装的属性配置元数据,加载META-INF/spring.factories数据

经过去除重复值,去掉需要剔除的值,经过filter过滤处理

2.2、getCandidateConfigurations

AutoConfigurationImportSelector#getCandidateConfigurations 查询带spring.factories文件的依赖包,获取所有值的键值对。通过EnableAutoConfiguration过滤出来需要自动加载的

image.png

AutoConfigurationImportSelector#getSpringFactoriesLoaderFactoryClass 表示只加载EnableAutoConfiguration类型的类

image.png 2.3、removeDuplicates

AutoConfigurationImportSelector#removeDuplicates 移除重复的通过LinkedHashSet集合接收,然后转成ArrayList

image.png 2.4、sort

对configurations集合排序 sort()

2.5、getExclusions

AutoConfigurationImportSelector#getExclusions 剔除exclude excludeName

image.png 2.6、checkExcludedClasses

checkExcludedClasses检查是否包含需要剔除的exclusions集合元素

image.png 2.7、filter

AutoConfigurationImportSelector#filter

image.png

对configurations集合中的元素通过AutoConfigurationImportFilter过滤器实现类OnClassCondition进行过滤 ①、match OnClassCondition#match

image.png ②、getOutcomes OnClassCondition#getOutcomes image.png

③、resolveOutcomes 分成两半调用resolveOutcomes方法 OnClassCondition.StandardOutcomesResolver#resolveOutcomes

image.png StandardOutcomesResolver#getOutcomes image.png PropertiesAutoConfigurationMetadata#get(String, String,String) image.png 拼接className和ConditionalOnClass的字符串从properties查找 StandardOutcomesResolver#getOutcomes方法返回没找到类的集合 image.png OnClassCondition.StandardOutcomesResolver#getOutcome image.png image.png image.png image.png

所以,ConditionOutcome集合存储的是加载不到的class 根据ConditionOutcome[] outcomes集合获取是否match匹配值的集合

image.png match是true,对不包含的进行跳过skip(true表示跳过,不包含) image.png image.png 对包含的元素放入到result集合并返回 image.png 2.8、fireAutoConfigurationImportEvents

AutoConfigurationImportSelector#fireAutoConfigurationImportEvents

image.png

AutoConfigurationImportSelector#invokeAwareMethods 为监听器对象ConditionEvaluationReportAutoConfigurationImportListener设置beanFactory值

image.png ConditionEvaluationReportAutoConfigurationImportListener#onAutoConfigurationImportEvent 创建ConditionEvaluationReport用来记录评估和日志的条件评估细节类,从bean工厂获取

condition.ConditionEvaluationReport#get beanName是autoConfigurationReport,ConditionEvaluationReport的条件评估细节类

image.png image.png 把evaluationCandidates和exclusions集合放入当前对象的属性中 image.png 最终是放到bean工厂的singletonOjects单例对象中 image.png 并selectImports方法返回configurations集合会放入到在processImports方法成配置类ConfigurationClass中 spring.factories数据与spring-autoconfigure-metadata.properties数据对应关系

基于2.1.x spring.factories

# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\

对于DispatcherServletAutoConfiguration、ServletWebServerFactoryAutoConfiguration、WebMvcAutoConfiguration类需要查找对于的spring-autoconfigure-metadata.properties的值 spring-autoconfigure-metadata.properties

org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration.ConditionalOnClass=org.springframework.web.servlet.DispatcherServlet org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration.ConditionalOnClass=javax.servlet.ServletRequest org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.ConditionalOnClass=javax.servlet.Servlet,org.springframework.web.servlet.config.annotation.WebMvcConfigurer,org.springframework.web.servlet.DispatcherServlet

如果能够加载org.springframework.web.servlet.DispatcherServlet类,则DispatcherServletAutoConfiguration会自动装配到bean工厂。 能够加载javax.servlet.ServletRequest,则ServletWebServerFactoryAutoConfiguration自动装配到bean工厂

ServletWebServerFactoryAutoConfiguration

查找过程与类上条件相同@ConditionalOnClass(ServletRequest.class)

image.png 加载tomcat

ServletWebServerFactoryAutoConfiguration类导入EmbeddedTomcat类,需要具有相关的类

image.png 说明:

本章源码分析是基于1.5.x 导入的类是EnableAutoConfigurationImportSelector EnableAutoConfigurationImportSelector实现了AutoConfigurationImportSelector 2.1.x 直接导入的类是AutoConfigurationImportSelector selectImports方法的实现过程是一样的,只是抽出了一个方法

image.png

AutoConfigurationImportSelector#getAutoConfigurationEntry

image.png 总结:

在自动装配中@ConditionalOnClass注解的使用 在自动配置SpringBootApplication注解中使用导入外部类方式: 1、实现了ImportBeanDefinitionRegistrar的类调用registerBeanDefinitions方法 2、实现了ImportSelector的类调用selectImports方法 @SpringBootApplication注解关键是如何读取数据并如何完成自动注入的 首先从所有依赖包查询spring-autoconfigure-metadata.properties文件,读取里面的数据加载到自动配置类元数据类中。 所有依赖包查询并获取spring.factories文件数据到集合中,然后经过去重,剔除处理。经过filter过滤步骤处理,会最终得到符合条件的类。 在这个关键步骤filter中,主要过程是: 1、spring.factories文件数据加载到集合的数据值拼接ConditionOnClass字段 2、对拼接后的值,在spring-autoconfigure-metadata.properties加载的自动配置类元数据类中(以键值对形式存在)。查找对应的值 3、对查找的值,通过类加载器查找是否能够加载到。返回一个match集合 4、通过match集合确定skip集合是否可以跳过 5、对于没有跳过的值,即可以通过类加载器加载的类放入到集合result中 6、selectImports方法的返回值result可以在spring bean的生命周期过程中加载这些类生成相应的bean 最终会加入到spring的bean工厂之中 最终效果是完成了springboot的自动配置



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有